# -*- coding: utf-8 -*-
from decimal import Decimal,getcontext,ROUND_HALF_DOWN
from random import randint
import re,time
from datetime import datetime,timedelta

from dtrader.price_handler import AbstractTickPriceHandler
from dtrader import logger
from dtrader.dataseries.tick import BasicTick
from dtrader.dataseries.tickds import TickDataSeries
from dtrader.event import TickEvent,EventType

try:
    from urllib.request import urlopen, Request
except ImportError:
    from urllib2 import urlopen, Request


class SinaRealtimeTickPriceHandler(AbstractTickPriceHandler):

    """
    从新浪财经获取tick数据
    """
    # 当天tick数据详情页
    TICK_URL = "http://hq.sinajs.cn/rn=%s&list=%s"

    #指数
    INDEX_LIST = {'sh': 'sh000001', 'sz': 'sz399001', 'hs300': 'sz399300',
                    'sz50': 'sh000016', 'zxb': 'sz399005', 'cyb': 'sz399006', 'zx300': 'sz399008', 'zh500': 'sh000905'}

    def __init__(self, events_queue, init_tickers):

        self.__logger = logger.getLogger("SINA_PRICE_HANDLER")
        self.events_queue = events_queue
        self.tickers_data = {}
        # 订阅行情，并初始化行情数据
        if init_tickers is not None:
            self.subscribe_tickers(init_tickers)


    def fetch_tick_loop(self):
        """循环获取tick行情"""
        while 1:
            tickers = self.tickers_data.keys()
            try:
                data = self.__fetch_tick_form_url(tickers)
                if data is not None and len(data) > 0:
                    for ticker, tick_data in data.iteritems():
                        date_time = tick_data['date_time']
                        ds = self.tickers_data[ticker]
                        last_date_time = ds.get_last_date_time()
                        if date_time <= last_date_time:
                            self.__logger.debug("no new data for %s after the time of %s"%(ticker, date_time))
                            continue

                        bid = tick_data['bid']
                        ask = tick_data['ask']
                        bid_volume = tick_data['bid_volume']
                        ask_volume = tick_data['ask_volume']

                        tick = BasicTick(date_time, bid, ask, bid_volume, ask_volume)
                        ds.append(tick)
                        # push event to the queue
                        tev = TickEvent(ticker, date_time, bid, ask, bid_volume, ask_volume)
                        self.events_queue.put(tev)
            except Exception as e:
                # log error
                self.__logger.error(e)
            time.sleep(1)

    def subscribe_tickers(self, tickers=[]):
        """订阅行情，并初始化行情数据"""
        if isinstance(tickers, str):
            tickers = [tickers]
        target_tickers = []
        for ticker in tickers:
            if ticker not in self.tickers_data.keys():
                target_tickers.append(ticker)

        data = self.__fetch_tick_form_url(target_tickers)
        if data is not None and len(data) > 0:
            for ticker, tick_data in data.iteritems():
                tick = BasicTick(tick_data['date_time'], tick_data['bid'], tick_data['ask'],
                                 tick_data['bid_volume'], tick_data['ask_volume'])
                ds = TickDataSeries()
                ds.append(tick)
                self.tickers_data[ticker] = ds

    def __fetch_tick_form_url(self, tickers):
        symbols_list = ''
        if isinstance(tickers, list) or isinstance(tickers, set) or isinstance(tickers, tuple):
            for ticker in tickers:
                symbols_list += self._ticker_to_symbol(ticker) + ','
        else:
            symbols_list = self._ticker_to_symbol(tickers)
        symbols_list = symbols_list[:-1] if len(symbols_list) > 8 else symbols_list
        try:
            url = SinaRealtimeTickPriceHandler.TICK_URL%(self._random(), symbols_list)
            self.__logger.debug("start request url:%s"%(url,))
            request = Request(url)
            text = urlopen(request,timeout=10).read()
            text = text.decode('GBK')
            self.__logger.debug("data from url:%s"%(text,))
            reg = re.compile(r'\="(.*?)\";')
            data = reg.findall(text)
            reg_tickers = re.compile(r'(?:sh|sz)(.*?)\=')
            tickers = reg_tickers.findall(text)

            ret = {}
            for index, row in enumerate(data):
                if len(row)>1:
                    tick_data = [astr for astr in row.split(',')]
                    ticker = tickers[index]
                    ret[ticker] = {}
                    ret[ticker]['name'] = tick_data[0]
                    ret[ticker]['date_time'] = datetime.strptime("%s %s"%(tick_data[-3], tick_data[-2]),"%Y-%m-%d %H:%M:%S")


                    getcontext().rounding = ROUND_HALF_DOWN
                    ret[ticker]['ask'] = Decimal(str(tick_data[11])).quantize(Decimal("0.00001"))
                    ret[ticker]['ask_volume'] = Decimal(str(tick_data[12])).quantize(Decimal("0.00001"))
                    ret[ticker]['bid'] = Decimal(str(tick_data[21])).quantize(Decimal("0.00001"))
                    ret[ticker]['bid_volume'] = Decimal(str(tick_data[22])).quantize(Decimal("0.00001"))
            return ret
        except Exception as e:
            # log error
            self.__logger.error(e)
            return {}

    def get_best_bid_ask(self, ticker):
        if not self.tickers_data.has_key(ticker):
            raise Exception("no ticker data of %s" % (ticker))
        lastTick = self.tickers_data[ticker][-1]
        if lastTick is not None and isinstance(lastTick, BasicTick):
            return lastTick.get_ask(), lastTick.get_bid()

    def _ticker_to_symbol(self, ticker):
        """
        生成symbol代码标志
        """
        if ticker in SinaRealtimeTickPriceHandler.INDEX_LIST.keys():
            return SinaRealtimeTickPriceHandler.INDEX_LIST[ticker]
        else:
            if len(ticker) != 6:
                return ''
            else:
                return 'sh%s'%ticker if ticker[:1] in ['5', '6', '9'] else 'sz%s'%ticker

    def _random(self, n=13):
        start = 10**(n-1)
        end = (10**n)-1
        return str(randint(start, end))

if __name__ == "__main__":

    try:
        import Queue as queue
    except ImportError:
        import queue

    import threading


    events = queue.Queue()

    price_handler = SinaRealtimeTickPriceHandler(events,['600479','300246'])
    price_handler.subscribe_tickers(['600172'])
    #tick_data = price_handler._SinaRealtimeTickPriceHandler__fetch_tick_form_url(["600479", "300246"])
    #print ticker_data
    #price_handler.fetch_tick_loop()
    price_thread = threading.Thread(target=price_handler.fetch_tick_loop,args=[])
    price_thread.setDaemon(True)
    price_thread.start()
    while 1:
        time.sleep(100)
